package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.learning.domain.enums.QuestionStatus.UN_CHECK;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2024-11-12
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final UserClient userClient;
    private final InteractionQuestionMapper questionMapper;
    @Override
    public void updateHiddenById(Long id, Boolean hidden) {
        // 获取指定id的回复
        InteractionReply reply = this.getById(id);

        // 如果回复存在
        if (ObjectUtil.isNotEmpty(reply)) {
            // 更新当前回复的隐藏状态
            this.lambdaUpdate()
                    .eq(InteractionReply::getId, id)
                    .set(InteractionReply::getHidden, hidden)
                    .update();

            // 收集所有需要更新的子评论ID
            List<Long> allChildIds = new ArrayList<>();
            collectChildReplyIds(reply.getId(), allChildIds);

            // 批量更新所有子评论的隐藏状态
            if (!allChildIds.isEmpty()) {
                this.lambdaUpdate()
                        .in(InteractionReply::getId, allChildIds)
                        .set(InteractionReply::getHidden, hidden)
                        .update();
            }
        }
    }


    private void collectChildReplyIds(Long parentId, List<Long> allChildIds) {
        // 获取所有子回复
        List<InteractionReply> childReplies = this.lambdaQuery()
                .eq(InteractionReply::getTargetReplyId, parentId)
                .list();

        // 如果存在子回复
        if (ObjectUtil.isNotEmpty(childReplies)) {
            for (InteractionReply childReply : childReplies) {
                // 添加子回复的ID到列表中
                allChildIds.add(childReply.getId());

                // 递归收集子回复的子回复的ID
                collectChildReplyIds(childReply.getId(), allChildIds);
            }
        }
    }

    /**
     * 新增回答或评论
     */
    @Override
    @Transactional
    public void saveReply(ReplyDTO replyDTO) {
        //1.先保存进互动回答表
        //1.1数据转换
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        //1.2保存并返回主键id
        reply.setUserId(UserContext.getUser());
        save(reply);
        //2.查询问题表是否存在该问题
        QueryWrapper<InteractionQuestion> queryWrapper = new QueryWrapper();
        queryWrapper.eq("id", replyDTO.getQuestionId());
        InteractionQuestion question = questionMapper.selectOne(queryWrapper);

        if (ObjectUtils.isEmpty(question)) {
            throw new RuntimeException("问题不存在");
        }

        //3.修改问题表
        //3.1记录最新回答的id
        Long answerId = reply.getId();
        //3.2修改问题表
        UpdateWrapper<InteractionQuestion> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", replyDTO.getQuestionId())
                .setSql(ObjectUtils.isNotEmpty(answerId), "answer_times = answer_times + 1")
                .set(ObjectUtils.isNotEmpty(replyDTO.getIsStudent()), "status", UN_CHECK)
                .set(ObjectUtils.isNotEmpty(answerId), "latest_answer_id", answerId);
        questionMapper.update(null, updateWrapper);


        //3.3修改回复表
        //上级评论的评论数应该加一
        if (ObjectUtils.isNotEmpty(replyDTO.getAnswerId())) {
            UpdateWrapper<InteractionReply> wrapper = new UpdateWrapper<>();
            wrapper.eq("id", replyDTO.getAnswerId())
                    .setSql("reply_times = reply_times + 1");
            this.update(wrapper);
        }
    }

    @Override
    public PageDTO<ReplyVO> pageQueryReplies(ReplyPageQuery query) {
        if (ObjectUtil.isEmpty(query.getQuestionId()) && ObjectUtil.isEmpty(query.getAnswerId())) {
            throw new RuntimeException("问题id和评论id不能同时为空");
        }
        Page<InteractionReply> replyPage = this.lambdaQuery()
                .eq(ObjectUtil.isNotEmpty(query.getQuestionId()), InteractionReply::getQuestionId, query.getQuestionId())
                .eq(ObjectUtil.isNotEmpty(query.getAnswerId()), InteractionReply::getAnswerId, query.getAnswerId())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionReply> records = replyPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(replyPage);
        }
        Set<Long> userIds = new HashSet<>();
        Set<Long> targetUserIds = new HashSet<>();
        //Set<Long> targetReplyIds = new HashSet<>();
        for (InteractionReply record : records) {
            userIds.add(record.getUserId());
            targetUserIds.add(record.getTargetUserId());
            //targetReplyIds.add(record.getTargetReplyId());
        }
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(userDTOS)) {
            userInfoMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }
        List<UserDTO> targetUserDTOS = userClient.queryUserByIds(targetUserIds);
        Map<Long, String> targetUserInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(targetUserDTOS)) {
            targetUserInfoMap = targetUserDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u.getName()));
        }
        List<ReplyVO> replyVOS = new ArrayList<>();
        for (InteractionReply record : records) {
            ReplyVO replyVO = BeanUtils.copyBean(record, ReplyVO.class);
            UserDTO userDTO = userInfoMap.get(record.getUserId());
            if (ObjectUtil.isNotEmpty(userDTO)) {
                replyVO.setUserName(userDTO.getName());
                replyVO.setUserIcon(userDTO.getIcon());
            }
            String targetUserName = targetUserInfoMap.get(record.getTargetUserId());
            if (ObjectUtil.isNotEmpty(targetUserName)) {
                replyVO.setTargetUserName(targetUserName);
            }

            replyVOS.add(replyVO);

        }

        return PageDTO.of(replyPage, replyVOS);
    }

    @Override
    public PageDTO<ReplyVO> pageQuery(ReplyPageQuery query) {
        //1.判断问题id和回答id是否存在
        if (ObjectUtils.isEmpty(query.getQuestionId()) && ObjectUtils.isEmpty(query.getAnswerId())) {
            throw new BadRequestException("问题id和回答id至少指定一个");
        }

        //2.先查询回复表
        Page<InteractionReply> page = null;
        //2.1如果只给了问题id，则查询出所有该问题的回复
        if (ObjectUtils.isEmpty(query.getAnswerId())) {
            page = this.lambdaQuery()
                    .eq(InteractionReply::getQuestionId, query.getQuestionId())
                    .eq(InteractionReply::getHidden, false)
                    .page(query.toMpPageDefaultSortByCreateTimeDesc());
            if(ObjectUtils.isNotEmpty(page.getRecords())){

                page.setRecords(page.getRecords().stream().filter(r -> r.getAnswerId().equals(0L)).collect(Collectors.toList()));
            }
        }
        //2.2如果只给了回答id，则查询出所有该回答的回复
        else if (ObjectUtils.isEmpty(query.getQuestionId())) {
            page = this.lambdaQuery().eq(InteractionReply::getAnswerId, query.getAnswerId())
                    .eq(InteractionReply::getHidden, false)
                    .page(query.toMpPageDefaultSortByCreateTimeDesc());
        }
        //2.3如果同时给了问题id和回答id，则查询出该回答的所有回复
        else {
            page = this.lambdaQuery()
                    .eq(InteractionReply::getAnswerId, query.getAnswerId())
                    .eq(InteractionReply::getQuestionId, query.getQuestionId())
                    .eq(InteractionReply::getHidden, false)
                    .page(query.toMpPageDefaultSortByCreateTimeDesc());
        }
        if (ObjectUtils.isEmpty(page.getRecords())) {
            return PageDTO.empty(0L, 0L);
        }
        List<InteractionReply> records = page.getRecords();
        //2.4如果查询结果为空，则直接返回
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        //3.收集其他字段数据

        //补充
        //先查问题表
        //如果answerid为空说明是回答问题
        Boolean isAnswer = null;
        Map<Long, Boolean> isAnswerMap = new HashMap<>();
        if (ObjectUtils.isEmpty(query.getAnswerId())) {
            //查询问题表获取该问题数据
            QueryWrapper<InteractionQuestion> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", query.getQuestionId());
            InteractionQuestion question = questionMapper.selectOne(queryWrapper);
            isAnswer = question.getAnonymity();
        } else {
            //查询回复表获取该回答数据是否匿名
            List<InteractionReply> list = this.lambdaQuery().eq(InteractionReply::getId, query.getAnswerId()).list();
            //收集成map
            isAnswerMap = list.stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getAnonymity));
        }


        if (ObjectUtils.isEmpty(isAnswer) && ObjectUtils.isEmpty(isAnswerMap)) {
            throw new RuntimeException("问题不存在");
        }

        //3.1收集用户ids
        HashSet<Long> userIds = new HashSet<>();
        for (InteractionReply record : records) {
            //增加非匿名的回答者id
            if (!record.getAnonymity()) {
                Long userId = record.getUserId();
                userIds.add(userId);
            }
            //增加非匿名的被评论用户id

            if (Boolean.FALSE.equals(isAnswer)) {
                //说明是回复非匿名
                Long targetUserId = record.getTargetUserId();
                userIds.add(targetUserId);
            }
            if (isAnswerMap.containsKey(record.getTargetReplyId())) {
                //说明是有这个id
                Boolean targetAnonymity = isAnswerMap.get(record.getTargetReplyId());
                if (!targetAnonymity) {
                    //说明被回复的回答者id非匿名
                    Long targetUserId = record.getTargetUserId();
                    userIds.add(targetUserId);
                }
            }
        }
        //3.2调用用户服务查询用户信息
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        //3.3收集成map
        Map<Long, UserDTO> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));

        //4.数据组装
        List<ReplyVO> replyVOs = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            //4.1数据拷贝
            ReplyVO replyVO = BeanUtils.copyBean(record, ReplyVO.class);
            //4.2填充用户字段
            if (ObjectUtils.isNotEmpty(record.getUserId())) {
                //判断是否匿名
                if (!record.getAnonymity()) {
                    replyVO.setUserName(userMap.getOrDefault(record.getUserId(), new UserDTO()).getName());
                    replyVO.setUserIcon(userMap.getOrDefault(record.getUserId(), new UserDTO()).getIcon());
                }
            }
            if (ObjectUtils.isNotEmpty(record.getTargetUserId())) {
                if (Boolean.FALSE.equals(isAnswer) ) {
                    replyVO.setTargetUserName(userMap.getOrDefault(record.getTargetUserId(), new UserDTO()).getName());
                }
                if (isAnswerMap.containsKey(record.getTargetReplyId())) {
                    Boolean targetAnonymity = isAnswerMap.get(record.getTargetReplyId());
                    if (!targetAnonymity) {
                        replyVO.setTargetUserName(userMap.getOrDefault(record.getTargetUserId(), new UserDTO()).getName());
                    }
                }
            }
            replyVOs.add(replyVO);

        }
        if (ObjectUtils.isEmpty(replyVOs)) {
            return PageDTO.empty(page);
        }
        //5.返回page
        return PageDTO.of(page, replyVOs);
    }
}
